package net.ebakker.tvseries.archive;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.ebakker.tvseries.main.Pair;
import net.ebakker.tvseries.reader.TorrentNameParser;

import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.impl.FileVolumeManager;
import com.github.junrar.rarfile.FileHeader;

public class ArchiveExtracter {

	private Map<String, Pair<String, File>> destinationMap;
	private final Set<File> extractedArchives = new HashSet<>();
	private final List<File> extractedFiles = new ArrayList<>();

	public ArchiveExtracter(Map<String, Pair<String, File>> seriesMap) {
		this.destinationMap = seriesMap;
	}

	public void extractFiles(List<File> torrents) {
		for (File torrent : torrents) {
			String[] rarFiles = torrent.list(new FilenameFilter() {

				@Override
				public boolean accept(File dir, String name) {
					return name.endsWith("rar");
				}
			});
			if (rarFiles != null && rarFiles.length > 0) {
				extractArchive(torrent, rarFiles[0]);
			}
		}
	}

	private void extractArchive(File folder, String filename) {
		Pair<String, Integer> torrentInfo = TorrentNameParser.parseTorrent(folder.getName());
		Pair<String, File> folderTypePair = destinationMap.get(torrentInfo.getLeft());
		if (folderTypePair == null) {
			return;
		}
		File destinationDir = folderTypePair.getRight();
		Integer seriesSeason = torrentInfo.getRight();

		File f = new File(folder, filename);
		Archive a = null;
		try {
			a = new Archive(new FileVolumeManager(f));
		} catch (IOException | RarException e) {
			e.printStackTrace();
		}
		if (a != null) {
			a.getMainHeader().print();
			FileHeader fh = a.nextFileHeader();
			while (fh != null) {
				try {
					String season =
							"doc".equals(folderTypePair.getLeft()) ? "" : "/Season " + seriesSeason;
					File out =
							new File(new File(destinationDir + season), fixSeries(
									torrentInfo.getLeft(), fh.getFileNameString().trim()));
					System.out.println(out.getAbsolutePath());
					FileOutputStream os = new FileOutputStream(out);
					a.extractFile(fh, os);
					os.close();
					extractedArchives.add(folder);
					extractedFiles.add(out);
				} catch (IOException | RarException e) {
					e.printStackTrace();
				}
				fh = a.nextFileHeader();
			}
		}
		extractedArchives.add(folder);

	}

	private String fixSeries(String seriesName, String trim) {
		if ("American Dad".equals(seriesName)) {
			Pattern p = Pattern.compile("(.*\\.S)(\\d\\d)(.*)");
			Matcher m = p.matcher(trim);
			m.find();
			int increasedSeason = Integer.parseInt(m.group(2)) + 1;
			trim = m.replaceFirst("$1" + increasedSeason + "$3");
		} else if ("Revolution 2012".equals(seriesName)) {
			trim = trim.replace("2012.", "");
		}
		return trim;
	}

	public Set<File> getExtractedArchives() {
		return extractedArchives;
	}

	public List<File> getExtractedFiles() {
		return extractedFiles;
	}
}
